package cn.qidd.keep.manage.controller.system;

import cn.qidd.keep.domain.core.Result;
import cn.qidd.keep.domain.document.QUser;
import cn.qidd.keep.domain.document.Resource;
import cn.qidd.keep.domain.document.Role;
import cn.qidd.keep.domain.document.User;
import cn.qidd.keep.domain.web.BaseController;
import cn.qidd.keep.domain.web.UserVO;
import cn.qidd.keep.manage.model.system.*;
import cn.qidd.keep.manage.repository.ResourceRepository;
import cn.qidd.keep.manage.repository.RoleRepository;
import cn.qidd.keep.manage.repository.UserRepository;
import com.google.common.collect.Sets;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.qidd.keep.domain.core.Constants.TOKEN;

/**
 * Created by sunyanping on 2018/9/17
 */
@RestController
@RequestMapping("/api/role")
@Api(value = "RoleController",description = "角色管理")
public class RoleController extends BaseController {

    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ResourceRepository resourceRepository;

    @PostMapping("/createRole")
    @ApiOperation(value = "创建角色", notes = "创建角色")
    public Result createRole(@ApiIgnore @RequestHeader(TOKEN) String token, @Validated @RequestBody RoleParams params) {
        UserVO userVO = getUserByToken(token);
        Role mongoRole = new Role();
        BeanUtils.copyProperties(params, mongoRole);
        mongoRole.setOperatorName(userVO.getUserName());
        mongoRole.setOperatorRealName(userVO.getRealName());
        mongoRole.setOperatorTime(new Date());
        roleRepository.save(mongoRole);
        return new Result(Result.Status.SUCCESS, "创建成功");
    }

    @PostMapping("/updateRole")
    @ApiOperation(value = "修改角色", notes = "修改角色")
    public Result updateRole(@ApiIgnore @RequestHeader(TOKEN) String token, @Validated @RequestBody UpdateRoleParams params) {
        UserVO userVO = getUserByToken(token);
        Optional<Role> optionalRole = roleRepository.findById(params.getId());
        if (!optionalRole.isPresent()) return new Result(Result.Status.FAILURE, "角色不存在");
        Role role = optionalRole.get();
        BeanUtils.copyProperties(params, role);
        role.setOperatorName(userVO.getUserName());
        role.setOperatorRealName(userVO.getRealName());
        role.setOperatorTime(new Date());
        roleRepository.save(role);
        return new Result(Result.Status.SUCCESS, "修改成功");
    }

    @GetMapping("/findRoleListByPage")
    @ApiOperation(value = "分页查询角色", notes = "分页查询角色")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "integer", paramType = "query",
                    value = "页数 (1..N)"),
            @ApiImplicitParam(name = "pageSize", defaultValue = "10", dataType = "integer", paramType = "query",
                    value = "每页大小"),
            @ApiImplicitParam(name = "sort", dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名1 asc,属性名2 desc. ")
    })
    public Result<Page<Role>> findRoleListByPage(Pageable pageable, @Validated RoleSearchParams params) {
        BooleanBuilder builder = params.generateSearchCondition();
        Page<Role> all = roleRepository.findAll(builder, pageable);
        return new Result<>(Result.Status.SUCCESS, all);
    }

    @DeleteMapping("/deleteRole/{id}")
    @ApiOperation(value = "删除角色", notes = "删除角色")
    public Result deleteRole(@PathVariable String id) {
        Role mongoRole = roleRepository.findById(id).orElseThrow(RuntimeException::new);
        if (userRepository.exists(QUser.user.roles.contains(mongoRole))) {
            return new Result(Result.Status.FAILURE, "角色正在使用，不允许删除");
        }
        roleRepository.deleteById(id);
        return new Result(Result.Status.SUCCESS, "删除成功");
    }

    @GetMapping("/queryUserListByRoleId/{id}")
    @ApiOperation(value = "根据角色ID分页查询用户列表", notes = "根据角色ID分页查询用户列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "integer", paramType = "query",
                    value = "页数 (1..N)", required = true),
            @ApiImplicitParam(name = "pageSize", defaultValue = "10", dataType = "integer", paramType = "query",
                    value = "每页大小", required = true),
            @ApiImplicitParam(name = "sort", dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名1 asc,属性名2 desc. ")
    })
    public Result<Page<User>> queryUserListByRoleId(@ApiIgnore Pageable pageable, @PathVariable String id) {
        Role mongoRole = roleRepository.findById(id).orElseThrow(RuntimeException::new);
        Page<User> all = userRepository.findAll(QUser.user.roles.contains(mongoRole), pageable);
        return new Result<>(Result.Status.SUCCESS, all);
    }

    @GetMapping("/findRoleResourceList/{id}")
    @ApiOperation(value = "角色资源", notes = "查询角色可选资源，标识出已选中的")
    public Result<List<RoleResourceModel>> findRoleResourceList(@PathVariable String id) {
        Role mongoRole = roleRepository.findById(id).orElseThrow(RuntimeException::new);
        Set<Resource> resources = mongoRole.getResources();
        List<Resource> all = resourceRepository.findAll();
        List<RoleResourceModel> collect = all.stream().map(e -> {
            RoleResourceModel model = new RoleResourceModel();
            BeanUtils.copyProperties(e, model);
            if (resources.contains(e)) {
                model.setSelected(true);
            }
            return model;
        }).collect(Collectors.toList());
        return new Result<>(Result.Status.SUCCESS, collect);
    }

    @PostMapping("/assignResourceToRole")
    @ApiOperation(value = "角色分配资源", notes = "角色分配资源")
    public Result assignResourceToRole(@ApiIgnore @RequestHeader(TOKEN) String token, @Validated @RequestBody AssignResourceParams params) {
        UserVO userVO = getUserByToken(token);
        Role mongoRole = roleRepository.findById(params.getRoleId()).orElseThrow(RuntimeException::new);
        mongoRole.setResources(Sets.newHashSet(resourceRepository.findAllById(params.getResourceId())));
        mongoRole.setOperatorName(userVO.getUserName());
        mongoRole.setOperatorRealName(userVO.getRealName());
        mongoRole.setOperatorTime(new Date());
        roleRepository.save(mongoRole);
        return new Result<>(Result.Status.SUCCESS, "分配成功");
    }



}
